package com.example.gateway.filter;

import cn.hutool.jwt.JWT;
import cn.hutool.jwt.JWTUtil;
import com.example.common.AppVariable;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.http.HttpStatusCode;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.List;

/**
 * 实现全局过滤器
 */
@Component
public class AuthFilter implements GlobalFilter, Ordered {

    // 排除非验证 是否携带 token 的 url
    private String[] skipAuthUrls = {"/user/add", "/user/login"};

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        String url = exchange.getRequest().getURI().getPath(); // 获取请求报头中的 token
        for (String authUrl : skipAuthUrls) {
            if (authUrl.equals(url)) {
                // 拦截的是非验证的 就继续往下执行
                return chain.filter(exchange);
            }
        }
        ServerHttpResponse response = exchange.getResponse();   // 获取返回对象

        // 从请求参数中获取 token
        List<String> tokens =
                exchange.getRequest().getHeaders().get(AppVariable.TOKEN_KEY);
        if (tokens == null || tokens.size() == 0) {   // 此时没有获取到 token
            response.setStatusCode(HttpStatus.UNAUTHORIZED);   // 没有权限
            return response.setComplete();
        }

        // 获取第一个 token
        String token = tokens.get(0);
        // JWT 验证 token 是否有效
        boolean flag = false;
        try {
            flag = JWTUtil.verify(token, AppVariable.JWT_KEY.getBytes()); // 通过密钥验证 token   如果是一个无效的token
        } catch (Exception e) {
            flag = false;
        }
        JWT jwt = null;
        if (!flag) {
            // 没有成功解析出来 token（失效）
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            return response.setComplete();
        } else {
            // 解析出 token，判断 token 是否过期
            jwt = JWTUtil.parseToken(token);
            // 得到过期时间
            Object obj = jwt.getPayload("exp");
            long time = Long.valueOf(obj.toString()); // 转换出来将时间
            if (System.currentTimeMillis() > time) {
                // 此时说明 token 过期了
                response.setStatusCode(HttpStatus.UNAUTHORIZED);
                return response.setComplete();
            }
        }
        // 将jwt获取到的用户信息存储到 response中
        String uid = jwt.getPayload("uid").toString();
        String manager = jwt.getPayload("manager").toString();
        response.getHeaders().set("uid", uid);
        response.getHeaders().set("manager", manager);
        // 将 uid 设置进行到 request 的 header 中
        ServerHttpRequest request = exchange.getRequest().mutate()
                .header("uid", uid)
                .header("manager", manager).build();

        return chain.filter(exchange.mutate().request(request).build()); // 继续执行后面的逻辑
    }

    @Override
    public int getOrder() {
        // 参数越小越先执行
        return 1;
    }
}
